package com.github.freegeese.maven.plugin.autocode.metadata;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * Created by Administrator on 2017/3/29.
 */
public enum TypeInfo {
    /*
    Mybatis 类型处理参考
    BooleanTypeHandler	java.lang.Boolean, boolean	数据库兼容的 BOOLEAN
    ByteTypeHandler	java.lang.Byte, byte	数据库兼容的 NUMERIC 或 BYTE
    ShortTypeHandler	java.lang.Short, short	数据库兼容的 NUMERIC 或 SHORT INTEGER
    IntegerTypeHandler	java.lang.Integer, int	数据库兼容的 NUMERIC 或 INTEGER
    LongTypeHandler	java.lang.Long, long	数据库兼容的 NUMERIC 或 LONG INTEGER
    FloatTypeHandler	java.lang.Float, float	数据库兼容的 NUMERIC 或 FLOAT
    DoubleTypeHandler	java.lang.Double, double	数据库兼容的 NUMERIC 或 DOUBLE
    BigDecimalTypeHandler	java.math.BigDecimal	数据库兼容的 NUMERIC 或 DECIMAL
    StringTypeHandler	java.lang.String	CHAR, VARCHAR
    ClobReaderTypeHandler	java.io.Reader	-
    ClobTypeHandler	java.lang.String	CLOB, LONGVARCHAR
    NStringTypeHandler	java.lang.String	NVARCHAR, NCHAR
    NClobTypeHandler	java.lang.String	NCLOB
    BlobInputStreamTypeHandler	java.io.InputStream	-
    ByteArrayTypeHandler	byte[]	数据库兼容的字节流类型
    BlobTypeHandler	byte[]	BLOB, LONGVARBINARY
    DateTypeHandler	java.util.Date	TIMESTAMP
    DateOnlyTypeHandler	java.util.Date	DATE
    TimeOnlyTypeHandler	java.util.Date	TIME
    SqlTimestampTypeHandler	java.sql.Timestamp	TIMESTAMP
    SqlDateTypeHandler	java.sql.Date	DATE
    SqlTimeTypeHandler	java.sql.Time	TIME
    ObjectTypeHandler	Any	OTHER 或未指定类型
    EnumTypeHandler	Enumeration Type	VARCHAR-任何兼容的字符串类型，存储枚举的名称（而不是索引）
    EnumOrdinalTypeHandler	Enumeration Type	任何兼容的 NUMERIC 或 DOUBLE 类型，存储枚举的索引（而不是名称）。
     */

    BIT("BIT", "-7", "1", "", "", "", "1", "true", "3", "false", "false", "false", "BIT", "0", "0", "0", "0", "10", Boolean.class),
    BOOL("BIT", "-7", "1", "", "", "", "1", "true", "3", "false", "false", "false", "BOOL", "0", "0", "0", "0", "10", Boolean.class),

    TINYINT("TINYINT", "-6", "3", "", "", "[(M)] [UNSIGNED] [ZEROFILL]", "1", "false", "3", "true", "false", "true", "TINYINT", "0", "0", "0", "0", "10", Byte.class),

    TINYINT_UNSIGNED("TINYINT UNSIGNED", "-6", "3", "", "", "[(M)] [UNSIGNED] [ZEROFILL]", "1", "false", "3", "true", "false", "true", "TINYINT UNSIGNED", "0", "0", "0", "0", "10", Byte.class),
    BIGINT("BIGINT", "-5", "19", "", "", "[(M)] [UNSIGNED] [ZEROFILL]", "1", "false", "3", "true", "false", "true", "BIGINT", "0", "0", "0", "0", "10", Long.class),
    BIGINT_UNSIGNED("BIGINT UNSIGNED", "-5", "20", "", "", "[(M)] [ZEROFILL]", "1", "false", "3", "true", "false", "true", "BIGINT UNSIGNED", "0", "0", "0", "0", "10", Long.class),
    LONG_VARBINARY("LONG VARBINARY", "-4", "16777215", "'", "'", "", "1", "true", "3", "false", "false", "false", "LONG VARBINARY", "0", "0", "0", "0", "10", byte[].class),
    MEDIUMBLOB("MEDIUMBLOB", "-4", "16777215", "'", "'", "", "1", "true", "3", "false", "false", "false", "MEDIUMBLOB", "0", "0", "0", "0", "10", byte[].class),
    LONGBLOB("LONGBLOB", "-4", "2147483647", "'", "'", "", "1", "true", "3", "false", "false", "false", "LONGBLOB", "0", "0", "0", "0", "10", byte[].class),
    BLOB("BLOB", "-4", "65535", "'", "'", "", "1", "true", "3", "false", "false", "false", "BLOB", "0", "0", "0", "0", "10", byte[].class),
    TINYBLOB("TINYBLOB", "-4", "255", "'", "'", "", "1", "true", "3", "false", "false", "false", "TINYBLOB", "0", "0", "0", "0", "10", byte[].class),
    VARBINARY("VARBINARY", "-3", "65535", "'", "'", "(M)", "1", "true", "3", "false", "false", "false", "VARBINARY", "0", "0", "0", "0", "10", byte[].class),
    BINARY("BINARY", "-2", "255", "'", "'", "(M)", "1", "true", "3", "false", "false", "false", "BINARY", "0", "0", "0", "0", "10", byte[].class),

    LONG_VARCHAR("LONG VARCHAR", "-1", "16777215", "'", "'", "", "1", "false", "3", "false", "false", "false", "LONG VARCHAR", "0", "0", "0", "0", "10", String.class),
    MEDIUMTEXT("MEDIUMTEXT", "-1", "16777215", "'", "'", "", "1", "false", "3", "false", "false", "false", "MEDIUMTEXT", "0", "0", "0", "0", "10", String.class),
    LONGTEXT("LONGTEXT", "-1", "2147483647", "'", "'", "", "1", "false", "3", "false", "false", "false", "LONGTEXT", "0", "0", "0", "0", "10", String.class),
    TEXT("TEXT", "-1", "65535", "'", "'", "", "1", "false", "3", "false", "false", "false", "TEXT", "0", "0", "0", "0", "10", String.class),
    TINYTEXT("TINYTEXT", "-1", "255", "'", "'", "", "1", "false", "3", "false", "false", "false", "TINYTEXT", "0", "0", "0", "0", "10", String.class),
    CHAR("CHAR", "1", "255", "'", "'", "(M)", "1", "false", "3", "false", "false", "false", "CHAR", "0", "0", "0", "0", "10", String.class),

    NUMERIC("NUMERIC", "2", "65", "", "", "[(M[,D])] [ZEROFILL]", "1", "false", "3", "false", "false", "true", "NUMERIC", "-308", "308", "0", "0", "10", Long.class),
    DECIMAL("DECIMAL", "3", "65", "", "", "[(M[,D])] [ZEROFILL]", "1", "false", "3", "false", "false", "true", "DECIMAL", "-308", "308", "0", "0", "10", BigDecimal.class),
    INTEGER("INTEGER", "4", "10", "", "", "[(M)] [UNSIGNED] [ZEROFILL]", "1", "false", "3", "true", "false", "true", "INTEGER", "0", "0", "0", "0", "10", Integer.class),
    INTEGER_UNSIGNED("INTEGER UNSIGNED", "4", "10", "", "", "[(M)] [ZEROFILL]", "1", "false", "3", "true", "false", "true", "INTEGER UNSIGNED", "0", "0", "0", "0", "10", Integer.class),
    INT("INTEGER", "4", "10", "", "", "[(M)] [UNSIGNED] [ZEROFILL]", "1", "false", "3", "true", "false", "true", "INT", "0", "0", "0", "0", "10", Integer.class),
    INT_UNSIGNED("INT UNSIGNED", "4", "10", "", "", "[(M)] [ZEROFILL]", "1", "false", "3", "true", "false", "true", "INT UNSIGNED", "0", "0", "0", "0", "10", Integer.class),
    MEDIUMINT("MEDIUMINT", "4", "7", "", "", "[(M)] [UNSIGNED] [ZEROFILL]", "1", "false", "3", "true", "false", "true", "MEDIUMINT", "0", "0", "0", "0", "10", Integer.class),
    MEDIUMINT_UNSIGNED("MEDIUMINT UNSIGNED", "4", "8", "", "", "[(M)] [ZEROFILL]", "1", "false", "3", "true", "false", "true", "MEDIUMINT UNSIGNED", "0", "0", "0", "0", "10", Integer.class),
    SMALLINT("SMALLINT", "5", "5", "", "", "[(M)] [UNSIGNED] [ZEROFILL]", "1", "false", "3", "true", "false", "true", "SMALLINT", "0", "0", "0", "0", "10", Short.class),
    SMALLINT_UNSIGNED("SMALLINT UNSIGNED", "5", "5", "", "", "[(M)] [ZEROFILL]", "1", "false", "3", "true", "false", "true", "SMALLINT UNSIGNED", "0", "0", "0", "0", "10", Short.class),
    FLOAT("FLOAT", "7", "10", "", "", "[(M,D)] [ZEROFILL]", "1", "false", "3", "false", "false", "true", "FLOAT", "-38", "38", "0", "0", "10", Float.class),
    DOUBLE("DOUBLE", "8", "17", "", "", "[(M,D)] [ZEROFILL]", "1", "false", "3", "false", "false", "true", "DOUBLE", "-308", "308", "0", "0", "10", Double.class),
    DOUBLE_PRECISION("DOUBLE PRECISION", "8", "17", "", "", "[(M,D)] [ZEROFILL]", "1", "false", "3", "false", "false", "true", "DOUBLE PRECISION", "-308", "308", "0", "0", "10", Double.class),
    REAL("REAL", "8", "17", "", "", "[(M,D)] [ZEROFILL]", "1", "false", "3", "false", "false", "true", "REAL", "-308", "308", "0", "0", "10", Double.class),

    VARCHAR("VARCHAR", "12", "65535", "'", "'", "(M)", "1", "false", "3", "false", "false", "false", "VARCHAR", "0", "0", "0", "0", "10", String.class),
    JSON("JSON", "1", "65535", "'", "'", "", "1", "false", "3", "false", "false", "false", "JSON", "0", "0", "0", "0", "10", String.class),
    ENUM("ENUM", "12", "65535", "'", "'", "", "1", "false", "3", "false", "false", "false", "ENUM", "0", "0", "0", "0", "10", String.class),
    SET("SET", "12", "64", "'", "'", "", "1", "false", "3", "false", "false", "false", "SET", "0", "0", "0", "0", "10", String.class),
    YEAR("YEAR", "91", "0", "'", "'", "", "1", "false", "3", "false", "false", "false", "YEAR", "0", "0", "0", "0", "10", Date.class),
    DATE("DATE", "91", "0", "'", "'", "", "1", "false", "3", "false", "false", "false", "DATE", "0", "0", "0", "0", "10", Date.class),
    TIME("TIME", "92", "0", "'", "'", "", "1", "false", "3", "false", "false", "false", "TIME", "0", "0", "0", "0", "10", Date.class),
    DATETIME("DATETIME", "93", "0", "'", "'", "", "1", "false", "3", "false", "false", "false", "DATETIME", "0", "0", "0", "0", "10", Date.class),
    TIMESTAMP("TIMESTAMP", "93", "0", "'", "'", "[(M)]", "1", "false", "3", "false", "false", "false", "TIMESTAMP", "0", "0", "0", "0", "10", Date.class);

    TypeInfo(String typeName, String dataType, String precision, String literalPrefix, String literalSuffix, String createParams, String nullable, String caseSensitive, String searchable, String unsignedAttribute, String fixedPrecScale, String autoIncrement, String localTypeName, String minimumScale, String maximumScale, String sqlDataType, String sqlDatetimeSub, String numPrecRadix, Class javaType) {
        this.typeName = typeName;
        this.dataType = dataType;
        this.precision = precision;
        this.literalPrefix = literalPrefix;
        this.literalSuffix = literalSuffix;
        this.createParams = createParams;
        this.nullable = nullable;
        this.caseSensitive = caseSensitive;
        this.searchable = searchable;
        this.unsignedAttribute = unsignedAttribute;
        this.fixedPrecScale = fixedPrecScale;
        this.autoIncrement = autoIncrement;
        this.localTypeName = localTypeName;
        this.minimumScale = minimumScale;
        this.maximumScale = maximumScale;
        this.sqlDataType = sqlDataType;
        this.sqlDatetimeSub = sqlDatetimeSub;
        this.numPrecRadix = numPrecRadix;
        this.javaType = javaType;
    }

    private String typeName;
    private String dataType;
    private String precision;
    private String literalPrefix;
    private String literalSuffix;
    private String createParams;
    private String nullable;
    private String caseSensitive;
    private String searchable;
    private String unsignedAttribute;
    private String fixedPrecScale;
    private String autoIncrement;
    private String localTypeName;
    private String minimumScale;
    private String maximumScale;
    private String sqlDataType;
    private String sqlDatetimeSub;
    private String numPrecRadix;

    private Class javaType;

    public String getTypeName() {

        return typeName;
    }

    public void setTypeName(String typeName) {
        this.typeName = typeName;
    }

    public String getDataType() {
        return dataType;
    }

    public void setDataType(String dataType) {
        this.dataType = dataType;
    }

    public String getPrecision() {
        return precision;
    }

    public void setPrecision(String precision) {
        this.precision = precision;
    }

    public String getLiteralPrefix() {
        return literalPrefix;
    }

    public void setLiteralPrefix(String literalPrefix) {
        this.literalPrefix = literalPrefix;
    }

    public String getLiteralSuffix() {
        return literalSuffix;
    }

    public void setLiteralSuffix(String literalSuffix) {
        this.literalSuffix = literalSuffix;
    }

    public String getCreateParams() {
        return createParams;
    }

    public void setCreateParams(String createParams) {
        this.createParams = createParams;
    }

    public String getNullable() {
        return nullable;
    }

    public void setNullable(String nullable) {
        this.nullable = nullable;
    }

    public String getCaseSensitive() {
        return caseSensitive;
    }

    public void setCaseSensitive(String caseSensitive) {
        this.caseSensitive = caseSensitive;
    }

    public String getSearchable() {
        return searchable;
    }

    public void setSearchable(String searchable) {
        this.searchable = searchable;
    }

    public String getUnsignedAttribute() {
        return unsignedAttribute;
    }

    public void setUnsignedAttribute(String unsignedAttribute) {
        this.unsignedAttribute = unsignedAttribute;
    }

    public String getFixedPrecScale() {
        return fixedPrecScale;
    }

    public void setFixedPrecScale(String fixedPrecScale) {
        this.fixedPrecScale = fixedPrecScale;
    }

    public String getAutoIncrement() {
        return autoIncrement;
    }

    public void setAutoIncrement(String autoIncrement) {
        this.autoIncrement = autoIncrement;
    }

    public String getLocalTypeName() {
        return localTypeName;
    }

    public void setLocalTypeName(String localTypeName) {
        this.localTypeName = localTypeName;
    }

    public String getMinimumScale() {
        return minimumScale;
    }

    public void setMinimumScale(String minimumScale) {
        this.minimumScale = minimumScale;
    }

    public String getMaximumScale() {
        return maximumScale;
    }

    public void setMaximumScale(String maximumScale) {
        this.maximumScale = maximumScale;
    }

    public String getSqlDataType() {
        return sqlDataType;
    }

    public void setSqlDataType(String sqlDataType) {
        this.sqlDataType = sqlDataType;
    }

    public String getSqlDatetimeSub() {
        return sqlDatetimeSub;
    }

    public void setSqlDatetimeSub(String sqlDatetimeSub) {
        this.sqlDatetimeSub = sqlDatetimeSub;
    }

    public String getNumPrecRadix() {
        return numPrecRadix;
    }

    public void setNumPrecRadix(String numPrecRadix) {
        this.numPrecRadix = numPrecRadix;
    }

    public Class getJavaType() {
        return javaType;
    }

    public void setJavaType(Class javaType) {
        this.javaType = javaType;
    }

    public String getJdbcType() {
        String typeName = getTypeName().replace(" ", "");
        List<String> texts = Arrays.asList(MEDIUMTEXT.name(), LONGTEXT.name(), TEXT.name(), TINYTEXT.name(), CHAR.name());
        if (texts.contains(typeName.toUpperCase())) {
            return VARCHAR.name();
        }
        return typeName;
    }

    public static TypeInfo valueByTypeName(String typeName) {
        if ("DATETIME".equalsIgnoreCase(typeName)) {
            return TIMESTAMP;
        }
        if ("LONGTEXT".equalsIgnoreCase(typeName)) {
            return LONG_VARCHAR;
        }
        return valueOf(typeName.replace(" ", "_"));
    }

}
